﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
using System.Threading;
using System.Windows.Forms;
using System.IO;

namespace TrabiBT
{
    public enum ReceptionState
    {
        Wait,
        Addr,
        Data
    }

    class Session
    {
        /* Bluetooth over serial port handler*/
        private static SerialPort bluetoothHandler;
        private Thread readThread = new Thread(ReadBT);
        private System.Windows.Forms.Timer sendTimer = new System.Windows.Forms.Timer();
        private static Dictionary<int,Variable> diagVars = new Dictionary<int,Variable>();
        private static Queue<byte> inputStream = new Queue<byte>();
        private static float data = 0;
        

        public Queue<byte> InputStream
        {
            get { return inputStream; }
        }

        public float Data
        {
            get { return data; }
        }
        public Session()
        {

             //diagVars.Add(0x20000008, new Variable(0x20000008, 0x3004,"float"));
             bluetoothHandler = new SerialPort(App.Instance.PortName);
             bluetoothHandler.DtrEnable = true;
             bluetoothHandler.BaudRate = 115200;
             bluetoothHandler.ReadTimeout = 500;
             bluetoothHandler.WriteTimeout = 500;

             sendTimer.Interval = 200;
             
             sendTimer.Tick += new EventHandler(SendRequest);

             ConnectToDevice();
             //try
             //{
             //    bluetoothHandler.Open();
             //    if (bluetoothHandler.IsOpen)
             //    {
             //        sendTimer.Enabled = true;
             //        readThread.Start();
             //        MessageBox.Show("Session started on" + App.Instance.PortName);
             //    }
             //}
             //catch(IOException)
             //{
             //    MessageBox.Show("Failed to open the selected port. (" + App.Instance.PortName+ ")");
             //}
             
        }

        public static void ReadBT()
        {
            byte[] message = new byte[1];
            byte[] addrparts = new byte[4];
            byte[] dataparts = new byte[10];
            int idAddr = 0;
            int num_of = 0;
            ReceptionState State = ReceptionState.Wait;
   
            while (true)
            {
                try
                {
                    //bluetoothHandler.Read(dataparts, 0, 9);
                    if (State == ReceptionState.Wait)
                    {
                        bluetoothHandler.Read(message, 0, 1);
                        if (message[0] == 0xAB)
                        {
                            State = ReceptionState.Addr;
                        }
                    }
                    if (State == ReceptionState.Addr)
                    {
                        bluetoothHandler.Read(addrparts, 0, 4);
                        idAddr = BitConverter.ToInt32(addrparts,0);
                        State = ReceptionState.Data;
                    }
                    if (State == ReceptionState.Data)
                    {
                        num_of = bluetoothHandler.Read(dataparts, 0, 4);
                        
                        if (diagVars.ContainsKey(idAddr))
                        {
                            if (diagVars[idAddr].Type == "float")
                            {
                                data = BitConverter.ToSingle(dataparts, 0);          
                            }
                            else if (diagVars[idAddr].Type == "int32")
                            {
                                data = BitConverter.ToInt32(dataparts, 0);
                            }
                            else
                            {
                                data = BitConverter.ToSingle(dataparts, 0);
                            }
                            diagVars[idAddr].CurrentValue = data;
                        }
                        State = ReceptionState.Wait;
                    }
                }
                catch (TimeoutException)
                {
                    //State = ReceptionState.Wait;
                }
            }
        }
        /* Send request to get variables*/
        public void SendRequest(Object myObject,  EventArgs myEventArgs)
        { 
            byte[] req_msg = new byte[10];
            /* Start frame*/
            req_msg[0] = 0xAB;
            foreach (var pair in diagVars)
            {
                /* Set global variable address*/
                for (int i = 0; i < 4; i++)
                {
                   req_msg[i + 1] = Convert.ToByte(pair.Value.AddrParts[i],16);
                }

                /* Set data field size*/
                req_msg[5] = (byte)pair.Value.Size;

                /**/
                for (int i = 0; i < pair.Value.Size; i++)
                {
                    req_msg[i + 6] = Convert.ToByte(pair.Value.DataParts[i], 16);
                }
                try
                {
                    bluetoothHandler.Write(req_msg, 0, (6 + pair.Value.Size));
                }
                catch (TimeoutException)
                {
                    //readThread.Abort();
                    //sendTimer.Enabled = false;
                    //App.Instance.MainForm.StatusLabel.Text = "Disconnected";
                }
            }
            
        }


        public void AddVar(int address, Variable var)
        {
            if (!(diagVars.ContainsKey(address)))
            {
                diagVars.Add(address, var);
            }
            else
            {
                MessageBox.Show("This address is already added!");
            }

           
        }

        public void UpdateData()
        {
            foreach (var pair in diagVars)
            {
                pair.Value.UpdateAllViews();
            }
        }

        public void ConnectToDevice()
        {
            try
            {
                if (bluetoothHandler.IsOpen == false)
                {
                    bluetoothHandler.Open();
                }
                sendTimer.Enabled = true;
                if (bluetoothHandler.IsOpen)
                {
                    
                    if (readThread.ThreadState == ThreadState.Unstarted)
                    {
                        readThread.Start();
                    }
                    App.Instance.MainForm.StatusLabel.Text = "Connected";
                    MessageBox.Show("Session started on" + App.Instance.PortName);
                }
            }
            catch (IOException)
            {
                MessageBox.Show("Failed to open the selected port. (" + App.Instance.PortName + ")");
            }
        }
    }
}
